//#include //#include // //using namespace std; // //void main() //{ // //dynamic memory allocation // //dynamic - changing - at runtime // //memory - memory for variables, normally arrays // //allocation - to set aside something // // int* p = NULL; // // // ... // int size; // cin >> size; // // while(true) // { // p = new int[size]; // // //... // delete []p; // } // // for(int i = 0; i < size; i++) // { // cin >> p[i]; // } // for(int i = 0; i < size; i++) // { // cout << p[i] << endl; // } //} #include #include using namespace std; const unsigned int HEADER_SIZE = 54; const unsigned int BYTES_PER_PIXEL = 3; struct FileHeader { char bfType[3]; unsigned int bfSize; unsigned short bfReserved1; unsigned short bfReserved2; unsigned int bfOffBits; }; struct InfoHeader { unsigned int biSize; unsigned int biWidth; unsigned int biHeight; unsigned short biPlanes; unsigned short biBitCount; unsigned int biCompression; unsigned int biSizeImage; unsigned int biXPelsPerMeter; unsigned int biYPelsPerMeter; unsigned int biClrUsed; unsigned int biClrImportant; }; struct Pixel { unsigned char blue; unsigned char green; unsigned char red; }; struct BitmapFile { FileHeader fileHeader; InfoHeader infoHeader; Pixel* pixels; }; int paddingBytesNeededPerRow(int width); int bytesPerRow(int width); void writeFileHeader(ofstream& fout, const FileHeader& fileHeader) { fout.write(fileHeader.bfType, 2); // this should read BM fout.write((char*)&fileHeader.bfSize,4); fout.write((char*)&fileHeader.bfReserved1,2); fout.write((char*)&fileHeader.bfReserved2,2); fout.write((char*)&fileHeader.bfOffBits,4); } void writeInfoHeader(ofstream& fout, const InfoHeader& infoHeader) { fout.write((char*)&infoHeader.biSize,4); fout.write((char*)&infoHeader.biWidth,4); fout.write((char*)&infoHeader.biHeight,4); fout.write((char*)&infoHeader.biPlanes,2); fout.write((char*)&infoHeader.biBitCount,2); fout.write((char*)&infoHeader.biCompression,4); fout.write((char*)&infoHeader.biSizeImage,4); fout.write((char*)&infoHeader.biXPelsPerMeter,4); fout.write((char*)&infoHeader.biYPelsPerMeter,4); fout.write((char*)&infoHeader.biClrUsed,4); fout.write((char*)&infoHeader.biClrImportant,4); } void writePixels(ofstream& fout, const Pixel* pixels, const InfoHeader& infoHeader) { int i = 0; unsigned int padding = 0; int paddingBytes = paddingBytesNeededPerRow(infoHeader.biWidth); for(int row = 0; row < infoHeader.biHeight; row++) { for(int column = 0;column < infoHeader.biWidth; column++) { fout.write((char*)&pixels[i].blue, 1); fout.write((char*)&pixels[i].green, 1); fout.write((char*)&pixels[i].red, 1); i++; } //may need to write extra bytes fout.write((char*)&padding,paddingBytes); } } void writeBitmapFile(char fileName[], const BitmapFile& bitmapFile) { ofstream fout(fileName,ios::binary); writeFileHeader(fout,bitmapFile.fileHeader); writeInfoHeader(fout,bitmapFile.infoHeader); writePixels(fout, bitmapFile.pixels, bitmapFile.infoHeader); fout.close(); } void readFileHeader(ifstream& fin, FileHeader& fileHeader) { fin.read(fileHeader.bfType, 2); // this should read BM fin.read((char*)&fileHeader.bfSize,4); fin.read((char*)&fileHeader.bfReserved1,2); fin.read((char*)&fileHeader.bfReserved2,2); fin.read((char*)&fileHeader.bfOffBits,4); } void readInfoHeader(ifstream& fin, InfoHeader& infoHeader) { fin.read((char*)&infoHeader.biSize,4); fin.read((char*)&infoHeader.biWidth,4); fin.read((char*)&infoHeader.biHeight,4); fin.read((char*)&infoHeader.biPlanes,2); fin.read((char*)&infoHeader.biBitCount,2); fin.read((char*)&infoHeader.biCompression,4); fin.read((char*)&infoHeader.biSizeImage,4); fin.read((char*)&infoHeader.biXPelsPerMeter,4); fin.read((char*)&infoHeader.biYPelsPerMeter,4); fin.read((char*)&infoHeader.biClrUsed,4); fin.read((char*)&infoHeader.biClrImportant,4); } void readPixels(ifstream& fin, Pixel* pixels, InfoHeader& infoHeader) { int i = 0; unsigned int padding = 0; int paddingBytes = paddingBytesNeededPerRow(infoHeader.biWidth); for(int row = 0; row < infoHeader.biHeight; row++) { for(int column = 0;column < infoHeader.biWidth; column++) { fin.read((char*)&pixels[i].blue, 1); fin.read((char*)&pixels[i].green, 1); fin.read((char*)&pixels[i].red, 1); i++; } //may need to read extra bytes fin.read((char*)&padding,paddingBytes); } } void readBitmapFile(char fileName[], BitmapFile& bitmapFile) { ifstream fin(fileName,ios_base::binary); readFileHeader(fin,bitmapFile.fileHeader); readInfoHeader(fin,bitmapFile.infoHeader); //asking form memory at runtime (dynamic memeory allocation) bitmapFile.pixels = new Pixel[bitmapFile.infoHeader.biWidth * bitmapFile.infoHeader.biHeight]; readPixels(fin, bitmapFile.pixels, bitmapFile.infoHeader); fin.close(); } int bytesPerRow(int width) { int result = width * 3; while(result % 4 != 0) { result ++; } return result; } int paddingBytesNeededPerRow(int width) { return ( bytesPerRow(width) - (width * 3)); } void rotate90(BitmapFile& bitmapFile) { Pixel* newPixels = new Pixel[bitmapFile.infoHeader.biWidth * bitmapFile.infoHeader.biHeight]; for(int row =0; row < bitmapFile.infoHeader.biHeight; row++) { for(int column =0; column < bitmapFile.infoHeader.biWidth; column++) { newPixels[(bitmapFile.infoHeader.biWidth - column - 1)*bitmapFile.infoHeader.biHeight + row] = bitmapFile.pixels[row * bitmapFile.infoHeader.biWidth + column]; } } delete []bitmapFile.pixels; bitmapFile.pixels = newPixels; unsigned int temp = bitmapFile.infoHeader.biWidth; bitmapFile.infoHeader.biWidth = bitmapFile.infoHeader.biHeight; bitmapFile.infoHeader.biHeight = temp; bitmapFile.infoHeader.biSizeImage = bytesPerRow(bitmapFile.infoHeader.biWidth) * bitmapFile.infoHeader.biHeight; bitmapFile.fileHeader.bfSize = bitmapFile.infoHeader.biSizeImage + HEADER_SIZE; } void main() { char fileName[100]; cout << "Enter the name of the bitmap file you want to edit\n"; cin.getline(fileName,100); BitmapFile bitmapFile; readBitmapFile(fileName, bitmapFile); //do the menu stuff if the file was there rotate90(bitmapFile); writeBitmapFile(fileName,bitmapFile); }